package com.liaoban.app.update;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.support.v4.app.NotificationCompat.Builder;
import android.support.v4.content.FileProvider;
import android.util.Log;

import com.liaoban.app.R;
import com.liaoban.app.api.type.event.AutoInstallEvent;
import com.liaoban.app.api.type.event.DownloadEvent;

import org.greenrobot.eventbus.EventBus;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import static android.os.Environment.MEDIA_MOUNTED;

/**
 * 应用升级安装服务，不适用断点续传
 */
public class UpdateService extends IntentService implements ApkUpdateConstants {

    private static final String EXTERNAL_STORAGE_PERMISSION = "android.permission.WRITE_EXTERNAL_STORAGE";

    private static final int BUFFER_SIZE = 10 * 1024; // 8k ~ 32K
    private static final String TAG = "DownloadService";
    private NotificationManager mNotifyManager;
    private Builder mBuilder;
    private boolean mIsInstalledAutomaticlly;
    private String mFileUrl;
    private File mApkFile;
    private UpdateServiceFinishCallback mServiceFinishCallback;
    private boolean mIsUpdateFinished;

    public UpdateService() {
        super("DownloadService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mBuilder = new Builder(this);

        String appName = getString(getApplicationInfo().labelRes);
//        int icon = getApplicationInfo().icon;

        mBuilder.setContentTitle(appName).setSmallIcon(R.mipmap.ic_logo);
        initData(intent);
        InputStream in = null;
        FileOutputStream out = null;
        try {
            URL url = new URL(mFileUrl);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(false);
            urlConnection.setConnectTimeout(10 * 1000);
            urlConnection.setReadTimeout(10 * 1000);
            urlConnection.setRequestProperty("Connection", "Keep-Alive");
            urlConnection.setRequestProperty("Charset", "UTF-8");
            urlConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");

            urlConnection.connect();
            long bytetotal = urlConnection.getContentLength();
            long bytesum = 0;
            int byteread = 0;
            in = urlConnection.getInputStream();
            File dir = getCacheDirectory(this);
            String apkName = mFileUrl.substring(mFileUrl.lastIndexOf("/") + 1, mFileUrl.length());
            mApkFile = new File(dir, apkName);
            out = new FileOutputStream(mApkFile);
            byte[] buffer = new byte[BUFFER_SIZE];

            int oldProgress = 0;

            while ((byteread = in.read(buffer)) != -1) {
                bytesum += byteread;
                out.write(buffer, 0, byteread);

                int progress = (int) (bytesum * 100L / bytetotal);
                // 如果进度与之前进度相等，则不更新，如果更新太频繁，否则会造成界面卡顿
                if (progress != oldProgress) {
                    updateProgress(progress);
                }
                oldProgress = progress;
                Log.e("yubch", "progress:" + progress);
                EventBus.getDefault().post(new DownloadEvent(progress));
            }
            // 下载完成
//            Log.e("yubch", "下载成功");
            mBuilder.setContentText("下载成功").setProgress(0, 0, false);

            Intent installAPKIntent = new Intent(Intent.ACTION_VIEW);
            //如果没有设置SDCard写权限，或者没有sdcard,apk文件保存在内存中，需要授予权限才能安装
            String[] command = {"chmod", "777", mApkFile.toString()};
            ProcessBuilder builder = new ProcessBuilder(command);
            builder.start();

            mIsUpdateFinished = true;
            if (mIsInstalledAutomaticlly) {
//                autoInstall();
                EventBus.getDefault().post(new AutoInstallEvent(mApkFile));
            } else {
                installAPKIntent.setDataAndType(Uri.fromFile(mApkFile), "application/vnd.android.package-archive");
                //installAPKIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                //installAPKIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                //installAPKIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

                PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, installAPKIntent, PendingIntent.FLAG_UPDATE_CURRENT);

                mBuilder.setContentIntent(pendingIntent);
                Notification noti = mBuilder.build();
                noti.flags = Notification.FLAG_AUTO_CANCEL;
                mNotifyManager.notify(0, noti);
            }

        } catch (Exception e) {
            Log.e(TAG, "download apk file error", e);
            mIsUpdateFinished = false;
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void initData(Intent intent) {
        if (null == intent) {
            Log.e(TAG, "intent is null");
            return;
        }
        mFileUrl = intent.getStringExtra(BUNDLE_KEY_APK_DOWNLOAD_URL);
        mIsInstalledAutomaticlly = intent.getBooleanExtra(BUNDLE_KEY_INSTALLED_AUTOMATICLLY, true);
        mServiceFinishCallback = (UpdateServiceFinishCallback) intent.getSerializableExtra(BUNDLE_KEY_FINISH_CALLBACK);
    }

    /*private void autoInstall() {
        *//*String type = "application/vnd.android.package-archive";
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(mApkFile), type);
        startActivity(intent);*//*

        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri data;
        // 判断版本大于等于7.0
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            // "net.csdn.blog.ruancoder.fileprovider"即是在清单文件中配置的authorities
            data = FileProvider.getUriForFile(this, "com.liaoban.app.fileprovider", mApkFile);
            // 给目标应用一个临时授权
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            data = Uri.fromFile(mApkFile);
        }
        intent.setDataAndType(data, "application/vnd.android.package-archive");
        startActivity(intent);
    }*/

    @Override
    public void onDestroy() {
        if (null != mServiceFinishCallback) {
            mServiceFinishCallback.isDownloadApkSuccessful(mIsUpdateFinished);
        }
        super.onDestroy();
    }

    private void updateProgress(int progress) {
        //"正在下载:" + progress + "%"
        mBuilder.setContentText(this.getString(R.string.update_download_progress, progress)).setProgress(100, progress, false);
        //setContentInent如果不设置在4.0+上没有问题，在4.0以下会报异常
        PendingIntent pendingintent = PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_CANCEL_CURRENT);
        mBuilder.setContentIntent(pendingintent);
        mNotifyManager.notify(0, mBuilder.build());
    }

    private File getCacheDirectory(Context context) {
        File appCacheDir = null;
        if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
            appCacheDir = getExternalCacheDir(context);
        }
        if (appCacheDir == null) {
            appCacheDir = context.getCacheDir();
        }
        if (appCacheDir == null) {
            Log.w(TAG, "Can't define system cache directory! The app should be re-installed.");
        }
        return appCacheDir;
    }

    private File getExternalCacheDir(Context context) {
        File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data");
        File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache");
        if (!appCacheDir.exists()) {
            if (!appCacheDir.mkdirs()) {
                Log.w(TAG, "Unable to create external cache directory");
                return null;
            }
            try {
                new File(appCacheDir, ".nomedia").createNewFile();
            } catch (IOException e) {
                Log.i(TAG, "Can't create \".nomedia\" file in application external cache directory");
            }
        }
        return appCacheDir;
    }

    private boolean hasExternalStoragePermission(Context context) {
        int perm = context.checkCallingOrSelfPermission(EXTERNAL_STORAGE_PERMISSION);
        return perm == PackageManager.PERMISSION_GRANTED;
    }

}
